package com.framework.base.taglib.ui;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyTagSupport;

import com.framework.base.cache.BdCache;
import com.framework.base.struts.Result;
import com.framework.base.util.BeanUtil;
import com.framework.main.sys.bd.domain.SysBdVO;
import com.framework.main.sys.bd.service.SysBdService;

/**
 * @Description:功能描述
 * @Company: www.51wuxia.com
 * @version 1.0
 * @Date 2011-6-16 上午12:18:48
 */
@SuppressWarnings("serial")
public class JSTLPropertyTag extends BodyTagSupport {

	// *********************************************************************
	// Internal state

	protected Object value; // tag attribute
	protected String def; // tag attribute
	protected boolean escapeXml; // tag attribute
	private boolean needBody; // non-space body needed?
	protected int maxlength;
	private boolean displayTitle;
	private String bdid;// 基础数据编号 用于减少对基础数据的关联

	// *********************************************************************
	// Construction and initialization

	public void setDisplayTitle(boolean displayTitle) {
		this.displayTitle = displayTitle;
	}

	/**
	 * Constructs a new handler. As with TagSupport, subclasses should not
	 * provide other constructors and are expected to call the superclass
	 * constructor.
	 */
	public JSTLPropertyTag() {
		super();
		init();
	}

	// resets local state
	private void init() {
		value = def = null;
		escapeXml = true;
		needBody = false;
		maxlength = 0;
		displayTitle = true;
	}

	// Releases any resources we may have (or inherit)
	public void release() {
		super.release();
		init();
	}

	// *********************************************************************
	// Tag logic

	// evaluates 'value' and determines if the body should be evaluted
	public int doStartTag() throws JspException {
		if(BdCache.bdMap.get(getBdid())==null){
			SysBdService bdService = (SysBdService) BeanUtil.getServiceBeanById("bdService");
			if (getBdid() != null && !"".equals(getBdid())) {
				try {
					Result result = bdService.getById(bdid);
					SysBdVO vo = (SysBdVO) result.getVo();
					value = vo.getBdValuef();
					BdCache.bdMap.put(vo.getIdf(), vo.getBdValuef());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}else{
			value=BdCache.bdMap.get(getBdid()).toString();
		}
		
		
		needBody = false; // reset state related to 'default'
		super.bodyContent = null; // clean-up body (just in case container is
									// pooling tag handlers)

		try {
			// print value if available; otherwise, try 'default'
			if (value != null) {
				out(pageContext, escapeXml,
						getResultbyLimitLength(value.toString(), maxlength),
						value.toString(), displayTitle);
				return SKIP_BODY;
			} else {
				// if we don't have a 'default' attribute, just go to the body
				if (def == null) {
					needBody = true;
					return EVAL_BODY_BUFFERED;
				}

				// if we do have 'default', print it
				if (def != null) {
					// good 'default'
					out(pageContext, escapeXml,
							getResultbyLimitLength(def.toString(), maxlength),
							def.toString(), displayTitle);
				}
				return SKIP_BODY;
			}
		} catch (IOException ex) {
			throw new JspException(ex.getMessage(), ex);
		}
	}

	// prints the body if necessary; reports errors
	public int doEndTag() throws JspException {
		try {
			if (!needBody)
				return EVAL_PAGE; // nothing more to do

			// trim and print out the body
			if (bodyContent != null && bodyContent.getString() != null)
				out(pageContext,
						escapeXml,
						getResultbyLimitLength(bodyContent.getString().trim(),
								maxlength), bodyContent.getString().trim(),
						displayTitle);
			return EVAL_PAGE;
		} catch (IOException ex) {
			throw new JspException(ex.getMessage(), ex);
		}
	}

	// *********************************************************************
	// Public utility methods

	/**
	 * Outputs <tt>text</tt> to <tt>pageContext</tt>'s current JspWriter. If
	 * <tt>escapeXml</tt> is true, performs the following substring replacements
	 * (to facilitate output to XML/HTML pages):
	 * 
	 * & -> &amp; < -> &lt; > -> &gt; " -> &#034; ' -> &#039;
	 */
	public static void out(PageContext pageContext, boolean escapeXml,
			String textsub, String text, boolean displayTitle)
			throws IOException {
		JspWriter w = pageContext.getOut();
		if (!escapeXml) {
			if (displayTitle
					&& (textsub.length() < text.length() + "...".length())) {
				w.write("<span title='");
				w.write(text);
				w.write("'>");
				w.write(textsub);
				w.write("</span>");
			} else {
				w.write(textsub);
			}
		} else {
			if (displayTitle
					&& (textsub.length() < text.length() + "...".length())) {
				w.write("<span title=\"");
				writeEscapedXml(text.toCharArray(), text.length(), w);
				w.write("\">");
				writeEscapedXml(textsub.toCharArray(), textsub.length(), w);
				w.write("</span>");
			} else {
				writeEscapedXml(textsub.toCharArray(), textsub.length(), w);
			}
		}
	}

	private static final int HIGHEST_SPECIAL = '>';
	private static char[][] specialCharactersRepresentation = new char[HIGHEST_SPECIAL + 1][];
	static {
		specialCharactersRepresentation['&'] = "&amp;".toCharArray();
		specialCharactersRepresentation['<'] = "&lt;".toCharArray();
		specialCharactersRepresentation['>'] = "&gt;".toCharArray();
		specialCharactersRepresentation['"'] = "&#034;".toCharArray();
		specialCharactersRepresentation['\''] = "&#039;".toCharArray();
	}

	/**
	 * 
	 * Optimized to create no extra objects and write directly to the JspWriter
	 * using blocks of escaped and unescaped characters
	 * 
	 */
	private static void writeEscapedXml(char[] buffer, int length, JspWriter w)
			throws IOException {
		int start = 0;
		for (int i = 0; i < length; i++) {
			char c = buffer[i];
			if (c <= HIGHEST_SPECIAL) {
				char[] escaped = specialCharactersRepresentation[c];
				if (escaped != null) {
					// add unescaped portion
					if (start < i) {
						w.write(buffer, start, i - start);
					}
					// add escaped xml
					w.write(escaped);
					start = i + 1;
				}
			}
		}
		// add rest of unescaped portion
		if (start < length) {
			w.write(buffer, start, length - start);
		}
	}

	private String getResultbyLimitLength(String result, int maxlength) {
		if (maxlength > 0) {
			result = result.length() > maxlength ? result.substring(0,
					maxlength) + "..." : result.substring(0, result.length());
		}
		return result;
	}

	public void setValue(Object value) {
		this.value = value;
	}

	// for tag attribute
	public void setDefault(String def) {
		this.def = def;
	}

	// for tag attribute
	public void setEscapeXml(boolean escapeXml) {
		this.escapeXml = escapeXml;
	}

	//
	public void setMaxlength(int maxlength) {
		this.maxlength = maxlength;
	}

	public String getBdid() {
		return bdid;
	}

	public void setBdid(String bdid) {
		this.bdid = bdid;
	}

}
